/*
    This file is part of QTau
    Copyright (C) 2013-2018  Tobias "Tomoko" Platen <tplaten@posteo.de>
    Copyright (C) 2013       digited       <https://github.com/digited>
    Copyright (C) 2010-2013  HAL@ShurabaP  <https://github.com/haruneko>

    QTau is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    SPDX-License-Identifier: GPL-3.0+
*/

#include "sinsyscoreconverter.h"

#include <QJsonObject>
#include "ustjkeys.h"

#define PPQN (480)
#define INCREMENT(delta) (delta/numerator/PPQN*denominator/4);

SinsyScoreConverter::SinsyScoreConverter() {
    pos_pulses = 0;//FIXME
    QJsonObject setup;
    setup[USER_AGENT] = "QTAU::SinsyScoreConverter";
    notes.push_back(setup);
}

bool SinsyScoreConverter::setEncoding(const std::string &encoding) {
    (void)encoding;
    // only sane encoding is utf8
    return true;
}

bool SinsyScoreConverter::addKeyMark(sinsy::ModeType modeType, int fifths) {
    (void)modeType;
    (void)fifths;
    //currently ignored in qtau -- keymap needed for key change events
    return true;
}

bool SinsyScoreConverter::addBeatMark(size_t beats, size_t beatType) {
    tmap.addTimeSignature(current_measure,beats,beatType);
    numerator = beats;
    denominator = beatType;
    return true;
}

bool SinsyScoreConverter::addTempoMark(double tempo) {

    tmap.addTempo(current_measure,tempo);
    return true;
}

// untested
bool SinsyScoreConverter::addSuddenDynamicsMark(
    sinsy::SuddenDynamicsType suddenDynamicsType) {
   // QJsonObject mark;
   // mark["suddenDynamicsType"] = (int)suddenDynamicsType;
   // ust.push_back(mark);
    return true;
}

bool SinsyScoreConverter::addGradualDynamicsMark(
    sinsy::GradualDynamicsType gradualDynamicsType) {
    //QJsonObject mark;
    //mark["gradualDynamicsType"] = (int)gradualDynamicsType;
    //ust.push_back(mark);
    return true;
}

QString TieType(sinsy::TieType tieType) {
    switch (tieType) {
    case sinsy::TIETYPE_BEGIN:
        return "TIETYPE_BEGIN";
    case sinsy::TIETYPE_END:
        return "TIETYPE_END";
    case sinsy::TIETYPE_NONE:
    default:
        return "TIETYPE_NONE";
    }
}
QString SlurType(sinsy::SlurType slurType) {
    switch (slurType) {
    case sinsy::SLURTYPE_BEGIN:
        return "SLURTYPE_BEGIN";
    case sinsy::SLURTYPE_END:
        return "SLURTYPE_BEGIN";
    case sinsy::SLURTYPE_NONE:
    default:
        return "SLURTYPE_NONE";
    }
}
QString SyllabicType(sinsy::SyllabicType syllabicType) {
    switch (syllabicType) {
    case sinsy::SYLLABICTYPE_BEGIN:
        return "SYLLABICTYPE_BEGIN";
    case sinsy::SYLLABICTYPE_END:
        return "SYLLABICTYPE_END";
    case sinsy::SYLLABICTYPE_MIDDLE:
        return "SYLLABICTYPE_MIDDLE";
    case sinsy::SYLLABICTYPE_SINGLE:
    default:
        return "SYLLABICTYPE_SINGLE";
    }
}

// FIXME: do not hardcode ppqn
bool SinsyScoreConverter::addNote(
    size_t duration, const std::string &lyric, size_t pitch,
    bool accent, bool staccato, sinsy::TieType tieType,
    sinsy::SlurType slurType, sinsy::SyllabicType syllabicType, bool breath) {
    duration /= 2;  // sinsy uses a different ppqn than utau

    QJsonObject note;
    QString tmp = QString::fromStdString(lyric);
    if (tmp == "") tmp = "a";
    note[NOTE_LYRIC] = tmp;
    note[NOTE_PULSE_LENGTH] = (int)duration;
    note[NOTE_PULSE_OFFSET] = pos_pulses;
    note[NOTE_KEY_NUMBER] = (int)pitch;
    note[XML_ACCENT] = accent;
    note[XML_STACATTO] = staccato;
    note[XML_TIETYPE] = TieType(tieType);
    note[XML_SLURTYPE] = SlurType(slurType);
    note[XML_SYLLABICTYPE] = SyllabicType(syllabicType);
    note[XML_BREATH] = breath;
    notes.push_back(note);
    pos_pulses += duration;
    current_measure += INCREMENT(duration);
    return true;
}

bool SinsyScoreConverter::addRest(size_t duration) {
    duration /= 2;
    //if (pos_pulses == 0) genSetup();
    pos_pulses += duration;
    current_measure += INCREMENT(duration);
    return true;
}

void SinsyScoreConverter::toJSON(QJsonArray& ust)
{
    QJsonArray json;
    tmap.toJson(json);
    QJsonObject obj = notes[0].toObject();
    obj.insert(TEMPOMAP,json);
    notes[0] = obj;
    ust = notes;
}
